package com.peng.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.peng.constant.Constants;
import com.peng.mapper.TPermissionMapper;
import com.peng.mapper.TRoleMapper;
import com.peng.mapper.TUserMapper;
import com.peng.mapper.TUserRoleMapper;
import com.peng.model.*;
import com.peng.query.BaseQuery;
import com.peng.query.UserQuery;
import com.peng.result.R;
import com.peng.service.TPermissionService;
import com.peng.service.TRoleService;
import com.peng.service.TUserRoleService;
import com.peng.service.TUserService;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static com.peng.constant.Constants.PAGE_SIZE;

@RestController
public class UserController implements UserDetailsService {

    @Autowired
    private TUserService tUserService;

    @Autowired
    private TUserMapper tUserMapper;

    @Autowired
    private TRoleMapper tRoleMapper;

    @Autowired
    private TPermissionMapper tPermissionMapper;

    @Autowired
    private MinioClient minioClient;


    /**
     * 登录查询
     *
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    //spring security 登录验证
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LambdaQueryWrapper<TUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TUser::getLogin_act, username);
        TUser tUser = tUserService.getOne(wrapper);
        if (tUser == null) {
            throw new UsernameNotFoundException("登录账号不存在");
        }
        TUserDetailsImpl tUserDetailsImpl = new TUserDetailsImpl(tUser);

        //查询一下当前用户的角色
        List<TRole> tRoleList = tRoleMapper.selectByUserId(tUser.getId());
        //字符串的角色列表
        List<String> stringRoleList = new ArrayList<>();
        tRoleList.forEach(tRole -> {
            stringRoleList.add(tRole.getRole());
        });
        tUserDetailsImpl.setRoleList(stringRoleList); //设置用户的角色

        //查询一下该用户有哪些菜单权限
        List<TPermission> menuPermissionList = tPermissionMapper.selectMenuPermissionByUserId(tUserDetailsImpl.getId());
        tUserDetailsImpl.setMenuPermissionList(menuPermissionList);

        //查询一下该用户有哪些功能权限
        List<TPermission> buttonPermissionList = tPermissionMapper.selectButtonPermissionByUserId(tUserDetailsImpl.getId());
        List<String> stringPermissionList = new ArrayList<>();
        buttonPermissionList.forEach(tPermission -> {
            stringPermissionList.add(tPermission.getCode());//权限标识符
        });
        tUserDetailsImpl.setPermissionList(stringPermissionList);//设置用户的权限标识符

        return tUserDetailsImpl;
    }

    //获取登录者user的信息
    @Transactional(rollbackFor = Exception.class)
    @GetMapping("/api/login/info")
    public R loginInfo(Authentication authentication) {
        //从Authentication 获取登录人信息
        TUserDetailsImpl tUserDetailsimpl = (TUserDetailsImpl) authentication.getPrincipal();
        return R.OK(tUserDetailsimpl);
    }

    //用户进行免登录
    //因为 filter 工具包自动验证token，所以当进入这个接口时肯定是 验证成功的
    @GetMapping("api/freeLogin")
    public R freeLogin() {
        return R.OK();
    }

    //以分页形式进行多个用户查询
    @PreAuthorize(value = "hasAuthority('user:list')")
    @Transactional(rollbackFor = Exception.class)
    @GetMapping("/api/users")   //required = false 表示参数可传不穿，反之必须穿
    public R userPage(@RequestParam(value="current",required = false) Integer current) {
        //当没传入参数时，初始化为1
        if(current == null) {current = 1;}
        IPage<TUser> tUserIPage = tUserMapper
                .selectUserPage(BaseQuery.builder().build(),
                                new Page<TUser>(current, Constants.PAGE_SIZE));
        return R.OK(tUserIPage);
    }

    //获取指定 id 用户的信息
    @PreAuthorize(value = "hasAuthority('user:view')")
    @Transactional(rollbackFor = Exception.class)
    @GetMapping("/api/user/{id}")
    public R userDetail(@PathVariable(value = "id") Integer id) {
        TUser tUser = tUserService.getById(id);
        return R.OK(tUser);
    }

    //新增用户
    @PreAuthorize(value = "hasAuthority('user:add')")
    @PostMapping("api/user")
    public R addUser(@ModelAttribute UserQuery userQuery, @RequestHeader(value = "Authorization") String token) {
        //token 是获取创建人的id
        userQuery.setToken(token);
        int save = tUserService.saveUser(userQuery);
        return save >= 1 ? R.OK() : R.FAIL();
    }

    //编辑用户
    @PreAuthorize(value = "hasAuthority('user:edit')")
    @PutMapping("api/user")
    public R updateUser(@ModelAttribute UserQuery userQuery, @RequestHeader(value = "Authorization") String token) {
        //token 是获取创建人的id
        userQuery.setToken(token);
        int update = tUserService.updateUser(userQuery);
        return update >= 1 ? R.OK() : R.FAIL();
    }

    //删除用户
    @PreAuthorize(value = "hasAuthority('user:delete')")
    @Transactional(rollbackFor = Exception.class)
    @DeleteMapping("api/user/{id}")
    public R deleteUser(@PathVariable(value = "id") Integer id) {
        Boolean delete = tUserService.removeById(id);
        return delete ? R.OK() : R.FAIL();
    }

    //批量删除用户
    @PreAuthorize(value = "hasAuthority('user:delete')")
    @Transactional(rollbackFor = Exception.class)
    @DeleteMapping(value = "/api/user")
    public R batchDelUser(@RequestParam(value = "ids") String ids) {
        //ids = "1,3,5,6,7,11,15";
        List<Integer> idList = Arrays.stream(ids.split(","))
                                .map(Integer::parseInt)
                                .collect(Collectors.toList());

        boolean batchDel = tUserService.removeByIds(idList);

        return batchDel ? R.OK() : R.FAIL();
    }

    //获取负责人
    @GetMapping(value = "/api/owner")
    public R owner() {
        List<TUser> ownerList = tUserService.getOwnerList();
        return R.OK(ownerList);
    }

}
